from ..types import Component
from bpy.props import CollectionProperty, PointerProperty, StringProperty, \
    IntProperty, FloatProperty, BoolProperty
from bpy.types import PropertyGroup, Menu, Panel, Operator,Screen,Object
import bpy
import os
import imp
from .project import *

#COMPONENTS FUNCS
def getComponents():
    obj = bpy.context.object
    
    components = {}
    for prop in dir(obj):
        if prop.startswith('component_'):
            for component in getattr(obj, prop):
                print(component)
                components[component.sort] = component
    data = []
    for num in sorted(components):
        data.append(components[num])
    return data

class ComponentPanel(Panel):
    bl_idname = 'components.panel'
    bl_label = 'Components'
    
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_context_type = 'OBJECT'
    
    def draw(self, context):
        layout = self.layout
        project = getProject()
        if not project.path == '':
            #draw components menu
            layout.menu('components.menu')
            
            
            
            #draw components on object
            for component in getComponents():
                show = component.show
                name = component.name
                
                box = layout.box()
                sp = box.split(0.9)
                
                icon = 'DISCLOSURE_TRI_RIGHT' if show else 'DISCLOSURE_TRI_DOWN'
                sp.prop(component, 'show', name, icon=icon, emboss=False)
                op = sp.operator('components.remove', icon='X')
                op.sort = component.sort
                box.prop(component, 'sort')
                if show:
                    for name in dir(component):
                        if name.startswith('property_'):
                            box.prop(component, name)
                            #val=getattr(component,name)
                        
                        
                        
class ComponentMenu(Menu):
    bl_label = 'Add Component'
    bl_idname = 'components.menu'
    draw_preset = 'preset_subdir'
    def draw(self, context):
        def getComponentsData():
            cs = set()
            project = getProject()
            for dat in os.walk(project.path):
                path,files=dat[0,2]
                for f in files:
                    if f.endswith('.py'):
                        mod_name = f.replace('.py', '', 1)
                        mod_path = os.path.join(path, f)
                        mod = imp.load_source(mod_name, mod_path)
                        for obj_name in dir(mod):
                            obj = getattr(mod, obj_name)
        
                            if type(obj) == type and issubclass(obj, Component) and obj.__module__ == mod_name:
                                cs.add((mod_path, mod_name, obj_name))
            return cs
        def drawOption(file, module, name):
            layout = self.layout
            op = layout.operator('components.add', name)
            op.path = file
            op.module = module
            op.name = name
            return op
        
        for file, mod, name in getComponentsData():
            drawOption(file, mod, name)
            
class EditorComponent(PropertyGroup):
    file = StringProperty(name='file', subtype='FILE_PATH')
    module = StringProperty(name='module')
    type = StringProperty(name='type')
    name = StringProperty(name='name')
    sort = IntProperty(name='sort')
    show = BoolProperty(name='show', default=True)
    
class AddComponent(Operator):
    bl_label = ''
    bl_idname = 'components.add'
    path = StringProperty(name='path')
    module = StringProperty(name='module')
    name = StringProperty(name='name')
    def _makeCollection(self):
        def makeprop(name, val):
            exchange = {int:IntProperty, float:FloatProperty,
                      str:StringProperty, bool:BoolProperty}
            val_type = type(val)
            if val_type in exchange:
                return exchange[val_type](name=name, default=val)
        """
        Create collection
        """
        module = imp.load_source(self.module, self.path)
        component = getattr(module, self.name)
        data = {}
        
        for name in dir(component):
            if not name.startswith('_'):
                val = getattr(component, name)
                prop = makeprop(name, val)
                if prop:
                    data['property_' + name] = prop
                
        new_type = type(self.name, (EditorComponent,), data)
        bpy.utils.register_class(new_type)
        setattr(Object, 'component_' + self.name, CollectionProperty(type=new_type))

    def execute(self, context):
        """
        Create a component within a collection
        """
        if not hasattr(Object, 'component_' + self.name):
            #Create collection when none exist
            self._makeCollection()
        #Add an object
        new = getattr(context.object, 'component_' + self.name).add()
        new.sort = len(getComponents())
        return {'FINISHED'}


class RemoveComponent(Operator):
    bl_label = ''
    bl_idname = 'components.remove'
    sort = IntProperty(name='sort')



    def execute(self, context):
        def sortComponents():
            components = enumerate(getComponents())
            for sort, c in components:
                print(sort, c)
                c.sort = sort + 1
        """
        Create a component within a collection
        """
        for c in getComponents():
            if c.sort == self.sort:
                master = getattr(bpy.context.object, 'component_' + c.type)
                for i in range(len(master)):
                    c = master[i]
                    if c.sort == self.sort:
                        master.remove(i)

        
        sortComponents()
        return {'FINISHED'}



